/*
    4路调光控制器协议实现
*/

var _ = require('lodash');
import XLog from "./XLog";
import { plus33H, minus33H, reverseHex, number2Hex, hex2Int, hex2float, hex2short, calcChecksum, array2Hex, Recv_Error_Def, Loop_Device_Base } from "./SerialCommon";

export const controller4wayConstant = {
    startFlag: "68",
    endFlag: "16",
    broadcastAddress: "AAAAAAAAAAAA",
    pos_address: 2,
    pos_control: 16,
    pos_datalen: 18,
    pos_datavalue: 20,
    control_broadcast_req: "13",
    control_broadcast_rsp: "93",
    control_query_rsp: "9E",
    control_setlampstate_req: "1E",
    control_setlampstate_rsp: "9E",
    control_setlamplight_req: "1E",
    control_setlamplight_rsp: "9E",
    // control_querydeviceinfo_req: "1E",
    // control_querydeviceinfo_rsp: "9E",
    control_querydeviceinfo_req: "11",
    control_querydeviceinfo_rsp: "91",
    datalen_broadcast: "06",
    datalen_setlampstate: "05",
    datalen_setlamplight: "05",
    addressLen: 6,                          // 设备地址码，6字节长
}

export const response4wayType = {
    unknown: 0,
    broadcast: 1,
    setlampstate: 2,
    setlamplight: 3,
    readlight: 4
}

export class SerialController4Way{
    static getAddressAtIndex(address, index){
        // 设备地址不足12位时，前面补0
        address = ("0".repeat(12) + address).slice(-12);
        return address.substr((controller4wayConstant.addressLen - index - 1) * 2, 2);
    }    
    
    static checkQueryDeviceAddressResponse(response){
        return (response.substr(controller4wayConstant.pos_control, 2) == controller4wayConstant.control_broadcast_rsp)
        && (response.substr(controller4wayConstant.pos_datalen, 2) == controller4wayConstant.datalen_broadcast);
    }
    
    static parserQueryDeviceAddressResponse(response){
        var result = "";
        // 判断控制码是否正确
        if (this.checkQueryDeviceAddressResponse(response)){
            result = minus33H(response.substr(controller4wayConstant.pos_datavalue, parseInt(response.substr(controller4wayConstant.pos_datalen,2), 16)*2));
        }
        return reverseHex(result);
    }
    
    static checkSetLampStateResponse(response){
        return (response.substr(controller4wayConstant.pos_control, 2) == controller4wayConstant.control_setlampstate_rsp)
        && (response.substr(controller4wayConstant.pos_datalen, 2) == controller4wayConstant.datalen_setlampstate);
    }
    
    static parserSetLampState(response){
        var result = [];
        if(this.checkSetLampStateResponse(response)){
            var res = minus33H(response.substr(controller4wayConstant.pos_datavalue + 8, 2));
            for(var i = 0; i < 8; i++){
                result.push({"lamp": i + 1, "state": (res >> i) & 1 })
            }
        }
        return result;
    }
  
    static checkSetLampLightResponse(response){
        return (response.substr(controller4wayConstant.pos_control, 2) == controller4wayConstant.control_setlamplight_rsp)
        && (response.substr(controller4wayConstant.pos_datalen, 2) == controller4wayConstant.datalen_setlamplight);
    }
    
    static parserSetLampLight(response){
        var result = [];
        if(this.checkSetLampLightResponse(response)){
            var res = minus33H(response.substr(controller4wayConstant.pos_datavalue + 8, 2));
            for(var i = 0; i < 8; i++){
                result.push({"lamp": i + 1, "light": (res >> i) & 1 })
            }
        }
        return result;
    }
    
    // static checkQueryDeviceInfoResponse(response){
    //     var value = "00006013";
    //     return (response.substr(controller4wayConstant.pos_control, 2) == controller4wayConstant.control_querydeviceinfo_rsp)
    //     && (minus33H(response.substr(controller4wayConstant.pos_datavalue, 8)) == value);
    // }
    
    // static parserQueryDeviceInfo(response, index){
    //     var result = [];
    //     var valid = hex2Int(minus33H(response.substr(controller4wayConstant.pos_datavalue + 10, 2)));
    //     // var startpos = controller4wayConstant.pos_datalen + 10 + 2;
    //     var startpos = 0;
    //     var interval = 22;
    //     var datavalue = minus33H(response.substr(controller4wayConstant.pos_datavalue + 12, parseInt(response.substr(controller4wayConstant.pos_datalen,2), 16)*2 - 12));
    //     // response = minus33H(response);
    //     if(this.checkQueryDeviceInfoResponse(response)){
            
    //         for(var i = 0; i < 8; i++){
    //             let item = {};
    //             var item_pos = startpos + interval * i;
    //             if ((valid>>i)&1){
    //                 item['valid'] = 1;
    //                 item['lamp'] = i + 1 + (index - 1)* Loop_Device_Base;
    //                 item['state'] = hex2Int(datavalue.substr(item_pos, 2)) & 1;
    //                 item['vol'] = hex2short(datavalue.substr(item_pos+2, 4)) * 0.1;
    //                 item['current'] = hex2short(datavalue.substr(item_pos+6, 4)) * 0.01;
    //                 item['power'] = hex2short(datavalue.substr(item_pos+10, 4));
    //                 item['leak'] = hex2short(datavalue.substr(item_pos+14, 4)) * 0.01;
    //                 item['light'] = hex2Int(datavalue.substr(item_pos+18, 2));
    //                 item['color'] = hex2Int(datavalue.substr(item_pos+20, 2));
    //                 result.push(item);
    //             }            
    //         }
    //     }
    //     return result;
    // }

    static checkQueryDeviceInfoResponse(response){
        // var value = "00006013";
        var value = "00006009";
        return (response.substr(controller4wayConstant.pos_control, 2) == controller4wayConstant.control_querydeviceinfo_rsp)
        && (minus33H(response.substr(controller4wayConstant.pos_datavalue, 8)) == value);
    }

    static parserQueryDeviceInfo(response, index){
        var result = [];
        // var valid = hex2Int(minus33H(response.substr(controller4wayConstant.pos_datavalue + 10, 2)));
        // // var startpos = controller4wayConstant.pos_datalen + 10 + 2;
        // var startpos = 0;
        // var interval = 22;
        // var datavalue = minus33H(response.substr(controller4wayConstant.pos_datavalue + 12, parseInt(response.substr(controller4wayConstant.pos_datalen,2), 16)*2 - 12));
        var datavalue = minus33H(response.substr(controller4wayConstant.pos_datavalue + 8, parseInt(response.substr(controller4wayConstant.pos_datalen,2), 16)*2 - 8));
        var startpos = 0;
        if(this.checkQueryDeviceInfoResponse(response)){
            for(var i = 0; i < 4; i++){
                let item = {};
                item['valid'] = 1; 
                item['lamp'] = i + 1 + (index - 1)* Loop_Device_Base;
                item['light'] = hex2Int(datavalue.substr(2*i, 2));
                result.push(item);
            }
        }
        return result;
    }
    
    //[{"lamp": 1, "valid": 1, "switch": 1}]
    static formatSetLampState(lamp){
        var result = "00006007";
        var valid = 0;
        var lampSwitch = 0;
        for(var i = 0; i < lamp.length; i++){
            var prop = lamp[i];
            valid |= prop['valid'] << (prop['lamp'] - 1);
            lampSwitch |= prop['switch'] << (prop['lamp'] - 1);
        }
        result = result + number2Hex(valid) + number2Hex(lampSwitch);
        return plus33H(result);
    }
    
    //[{"lamp": 1, "valid": 1, "light": 50}]
    static formatSetLampLight(lamp){
        var result = "00006009";
        var valid = 0;
    
        // 对lamp字段进行排序
        lamp = _.sortBy(lamp, function(item){
            return item['lamp'];
        })
    
        for(var i = 0; i < lamp.length; i++){
            var prop = lamp[i];
            valid |= prop['valid'] << (prop['lamp'] - 1);
        }
        result = result + number2Hex(valid);
        for(var i = 0; i < lamp.length; i++){
            var prop = lamp[i];
            result = result + number2Hex(prop['light']);
        }
        return plus33H(result);
    }

    static fetchResponseAddress(response){
        let address = response.substr(controller4wayConstant.pos_address, 12);
        return reverseHex(address);
    }
    
    static getMessageType(response){
        // return response.substr(controller4wayConstant.pos_control, 2);
        var typeSetLampState = "00006007";
        var typeSetLampLight = "00006009";
        var typeQueryDevice = "00006013";
        var controllercode = response.substr(controller4wayConstant.pos_control, 2);
        if(controllercode == controller4wayConstant.control_broadcast_rsp){
            return response4wayType.broadcast;
        } else if(controllercode == controller4wayConstant.control_setlamplight_rsp){
            var typecode = response.substr(controller4wayConstant.pos_datavalue, 8);
            if(typecode == plus33H(typeSetLampLight)){
                return response4wayType.setlamplight;
            } 
            else {
                XLog.e("getMessageType error: ", response);
                return response4wayType.unknown;
            }
        }else if(controllercode == controller4wayConstant.control_querydeviceinfo_rsp){
            var typecode = response.substr(controller4wayConstant.pos_datavalue, 8);
            if(typecode == plus33H(typeSetLampLight)){
                return response4wayType.readlight;
            } 
            else {
                XLog.e("getMessageType error: ", response);
                return response4wayType.unknown;
            }
        }
        else{
            XLog.e("getMessageType error: ", response);
            return response4wayType.unknown;
        }
    }
    
    static generateRequest(address, control, dateLen, dataValue){
        var result = new Array();
        result.push(controller4wayConstant.startFlag);      // 插入开始帧
        // 插入设备地址码
        for(var i = 0; i < controller4wayConstant.addressLen; i++){
            result.push(this.getAddressAtIndex(address, i));
        }
        result.push(controller4wayConstant.startFlag);      // 插入开始帧
        result.push(control);                           // 插入控制码
        result.push(number2Hex(dateLen));               // 插入数据长度
        for(var i = 0; i < dateLen; i++){               // 插入数据内容
            result.push(dataValue.substr(i*2, 2));
        }
        result.push(calcChecksum(result));              // 插入校验和
        result.push(controller4wayConstant.endFlag);        // 插入结束符
        return array2Hex(result);
    }

    // 12 个长度以外的数据，包括起始码(1) + 地址(6) + 起始码(1) + 功能码(1) + 长度(1) + 校验和(1) + 结束码(1)
    static checkRecvLen(msg){
        const lenFormat = 12;
        if(msg.substr(0, 2) != controller4wayConstant.startFlag){
            return Recv_Error_Def.ERR_START_FLAG;
        }
        if (msg.length < controller4wayConstant.pos_datalen + 2){
            return Recv_Error_Def.ERR_NOT_ENOUGH_LEN;
        }

        let dataLen = hex2Int(msg.substr(controller4wayConstant.pos_datalen, 2));
        let expectLen = (dataLen + lenFormat) * 2;

        if (msg.length < expectLen){
            return Recv_Error_Def.ERR_NOT_ENOUGH_LEN;
        }
        let byte2calc = msg.substr(0, expectLen - 4);
        // console.log("msg: ", msg);
        // console.log("byte2calc: ", byte2calc);
        // let checksum_calc = calcChecksum(byte2calc);
        // let checksum_recv = msg.substr(expectLen - 4, 2);
        // console.log("checksum_calc: ", checksum_calc);
        // console.log("checksum_recv: ", checksum_recv);
        if(calcChecksum(msg.substr(0, expectLen - 4)) != msg.substr(expectLen - 4, 2)){
            return Recv_Error_Def.ERR_CHECKSUM;
        }
        return expectLen;
    }
}